<?php
// *** Tangra (Application Framework and Tools for PHP)
// $Id$
//

require_once(TANGRA_MAIN_DIR.'form/guardable_form.class.php');
require_once(TANGRA_MAIN_DIR.'form/form_guard.class.php');
require_once(TANGRA_MAIN_DIR.'web_site/redirect_composer_local.class.php');
require_once(TANGRA_MAIN_DIR.'web_site/web_page/just_headers_view.class.php');

require_once(TANGRA_MAIN_DIR.'exceptions/tangra_module_exception.class.php');


require_once($WSC->get_site_inc_dir().'_sys/site_web_page_wed.class.php');


abstract class Site_Page_W_GForm extends Site_Web_Page_WED {
	protected $form;
	protected $form_guarded_pairs;
	private $processed_states;
	protected $form_guard;
	protected $redir_on_success;



	function __construct($page_name, $redir_on_success_target_page) {
		parent::__construct($page_name);

		$this->redir_on_success = new Redirect_Composer_Local($this->get__context(), $redir_on_success_target_page);
	}


	public function get_redir_on_success() {
		return $this->redir_on_success_target_page;
	}


	public function default_event() {
		return $this->mode_form();
	}


	public function init() {
		parent::init();

		$v = $this->create_view();
		$this->add_view($v);


		$svm = $this->get_svm();

		if (!$svm->is_page_var_registered($this->get_page_name(), 'form_guarded_pairs')) {
			$svm->register_page_var($this->get_page_name(), 'form_guarded_pairs');
			$svm->set_page_var($this->get_page_name(), 'form_guarded_pairs', new Vars_Manager());
		}
		$this->form_guarded_pairs = &$svm->get_page_var($this->get_page_name(), 'form_guarded_pairs');


		if (!$svm->is_page_var_registered($this->get_page_name(), 'processed_states')) {
			$svm->register_page_var($this->get_page_name(), 'processed_states');
			$svm->set_page_var($this->get_page_name(), 'processed_states', new Vars_Manager());
		}
		$this->processed_states = &$svm->get_page_var($this->get_page_name(), 'processed_states');


		$this->form = $this->_create_form();
		$this->init_events();
//			$form_gen = new Static_HTML_Form_Generator($this->form, 'form/static/classic/', 'en');
//			$form_gen->create_default_tpl_maps();
//			printbr(htmlentities($form_gen->get_static_html()));

		$this->form_guard = new Form_Guard($this->form, $this->form_guarded_pairs);
	}


	protected function init_events() {
		$this->wed->add_wed_event_action_pair($this->form->get_submit_event(), 'handle_submit');
	}


	protected function handle_submit() {
		$context = $this->get__context();

		$this->form->capture_submit($context);

		$form_id = $this->form->get_field_html_value('form_id');
		if ($this->form_guard->is_fresh_submit($form_id)) {
			$ret = $this->handle_fresh_submit($form_id);
		} else {
			$ret = $this->handle_repeated_submit($form_id);
		}

		return $ret;
	}


	private function handle_fresh_submit($form_id) {
		//it is first submit of this form
		$this->form->basic_check();
		$this->form->accept_submit();
		$this->on_accepted_submit();

		if ($this->form->is_form_ok()) {
			if ($this->on_good_submit($this->form)) {
				$this->on_process_submit();
				$this->add_processed_state($form_id, true);
				$ret = $this->mode_ok($this->form, $this->get__exports());
			} else {
				$this->add_processed_state($form_id, false);
				$ret = $this->mode_form($this->form, $this->get__exports());
			}
		} else {
			$this->on_bad_submit();
			$this->add_processed_state($form_id, false);
			$ret = $this->mode_form($this->form, $this->get__exports());
		}

		return $ret;
	}


	private function handle_repeated_submit($form_id) {
		//second+ submit. Cause: double click on submit button, or refreshed page
		if ($this->is_already_processed($form_id)) {
			//we have already processed this event, just show them last result
			$last_state = $this->get_processed_state($form_id);
			if ($last_state) {
				$ret = $this->mode_ok($this->form, $this->get__exports());
			} else {
				$this->form->basic_check();
				$this->form->accept_submit();
				$this->on_accepted_submit();

				if ($this->form->is_form_ok()) {
					$this->on_good_submit($this->form);
				}

				$ret = $this->mode_form($this->form, $this->get__exports());
			}

		} else {
			// we never generated such guarded pair, so we assume
			// that this is hackers activity and we are closing application immediatly.
			// exception can be changed to more concrete class if you intend to intercept it
			throw new Tangra_Module_Exception('Form protection detected abnormal condition.');
		}

		return $ret;

	}


	protected function mode_form() {
		$this->form_guard->new_guard_pair();

		$this->on_mode_form();
		$this->prepare_form_view($this->form, $this->get__exports());

		$ret = $this->get_view('default');


		return $ret;
	}


	private function mode_ok() {
		$redir_view = new Just_Headers_View();
		$redir_view->add_http_header($this->redir_on_success->get_location($this->get__context()));

		return $redir_view;
	}


	private function _create_form() {
		$form = $this->create_form();
		if (!($form instanceof Guardable_Form)) {
			throw new Tangra_Module_Exception('Guardable_Form expected.');
		}

		return $form;
	}


	private function add_processed_state($form_id, $state) {
		$this->processed_states->register_var($form_id.'_processed');
		$this->processed_states->set_var($form_id.'_processed', $state);
	}


	private function is_already_processed($form_id) {
		return $this->processed_states->is_var_registered($form_id.'_processed');
	}


	private function get_processed_state($form_id) {
		return $this->processed_states->get_var($form_id.'_processed');
	}


	abstract protected function create_form();


	abstract protected function prepare_form_view(Guardable_Form $form, TPLE_Exports $exports);


	abstract protected function on_good_submit();


	abstract protected function on_bad_submit();


	abstract protected function on_accepted_submit();


	abstract protected function on_process_submit();


	abstract protected function on_mode_form();
}



